home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Just Call Me Internet
/
Just Call Me Internet.iso
/
prog
/
mint
/
bed02
/
bed.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-15
|
49KB
|
1,757 lines
/* BED - Bermuda EDitor */
/* (c) Vincent Pomey - 1993 */
/* free to use - do not complain */
/* $Id: bed.c,v 1.3 1993/08/15 20:53:32 vincent Exp $ */
/* v 0.0 oct 92 start */
/* v 0.1 feb 93 first release */
/* v 0.2 apr 93 fixes(quote...) */
/* $Log: bed.c,v $
* Revision 1.3 1993/08/15 20:53:32 vincent
* plein de petits bugs
*
* Revision 1.2 1993/06/15 17:19:56 vincent
* Print message
* */
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <Xm/RowColumn.h>
#include <Xm/MainW.h>
#include <Xm/CascadeB.h>
#include <Xm/CascadeBG.h>
#include <Xm/PushB.h>
#include <Xm/PushBG.h>
#include <Xm/LabelG.h>
#include <Xm/SeparatoG.h>
#include <Xm/Text.h>
#include <Xm/TextF.h>
#include <Xm/SelectioB.h>
#include <Xm/MessageB.h>
#include <Xm/FileSB.h>
#include <Xm/ToggleBG.h>
#include <Xm/Frame.h>
#include <X11/StringDefs.h>
#include "bed.h"
#include "missing.h"
#include "bed.xbm"
Widget RowCol, TextWidget, AreaWidget, FromWidget, ToWidget, DateWidget, SubjWidget;
XtAppContext App;
int ourzone, ournet, ournode, ourpoint;
char sysop[80];
int curr_area=-1, num_msgs, curr_msg;
FILE *texts=NULL;
struct Hdr *headers;
int num_areas; /* number of areas */
char *edit_cmd;
char temp1[50], temp2[50];
#define Str(a,b) XtVaTypedArg, a, XmRString, b, strlen(b)+1
int echozone, echonet, echonode, echopoint; /* original of the current echomail message */
char replyid[25]; /* msgid of the current message */
static XtResource ressources[] = {{
"editor",
"Editor",
XtRString, sizeof(String),
0,
XtRString, "xterm -e vi"
},
};
void ParseAdr (char *dest, int *zone, int *net, int *node, int *point)
{
char *nodea;
int i;
*zone=ourzone;
*net=ournet;
*node=ournode;
*point=0;
nodea=rindex(dest, '@');
if (!nodea)
nodea=rindex(dest, '(');
if (nodea) {
if (rindex(nodea+1, ':'))
sscanf (nodea+1, "%d:%d/%d.%d", zone, net, node, point);
else
sscanf (nodea+1, "%d/%d.%d", net, node, point);
if (nodea[-1]==' ') nodea[-1]=0; /* bidouille pour eviter un espace a la fin du nom */
else nodea[0]=0;
}
else {
/* no address -> scan user list */
FILE *users;
char ligne[100], *p, *q;
p=getenv ("MAILER");
if (p)
sprintf (ligne, "%s/ulist.txt", p);
else
strcpy (ligne, "ulist.txt");
users=fopen (ligne, "r");
if (users != NULL) {
/* mets les majuscules */
if (strlen (dest)==2)
strupr (dest);
else {
*dest = toupper (*dest);
if (p=rindex (dest, ' ')) {
p++;
*p=toupper (*p);
}
}
while (!feof(users)) {
if (fgets (ligne, 100, users)) {
/* split name/address */
if (p=rindex(ligne, '\t'))
*p=0;
else
break; /* format non valide */
/* check initials */
if (strlen(dest)==2)
if ((ligne[0]==*dest) && (q=rindex(ligne, ' ')) && (q[1] = dest[1]))
strcpy (dest, ligne);
if (!stricmp (dest, ligne)) {
sscanf (p+1, "%d:%d/%d.%d", zone, net, node, point);
/* break; no break since we should check for the latest entry (add in ulist
does not remove previous entry. hu hu hu it's ugly */
}
}
}
fclose (users);
}
}
i=strlen(dest)-1;
while ((i != 0) && ((dest[i]==' ') || (dest[i]=='\t')))
i--;
if ((dest[i]==' ') || (dest[i]=='\t'))
dest[i]=0;
}
/*#define OK_ISO_LATIN1*/
/* very limited conversion from PC character set to ISO Latin1 */
char Pc2Iso (unsigned char t)
{
#ifdef OK_ISO_LATIN1
/* my Motif doesn't like that, dunno why */
if (t==133) t=224; /* a' */
if (t==130) t=233; /* e' */
if (t==138) t=232; /* e` */
if (t==145) t=231; /* c, */
if (t==151) t=249; /* u` */
#else
if (t==133) t='a'; /* a' */
if (t==130) t='e'; /* e' */
if (t==138) t='e'; /* e` */
if (t==145) t='c'; /* c, */
if (t==151) t='u'; /* u` */
#endif
return t;
}
/* General Motif functions */
void Focus (Widget w)
{
/* twice because of Motif bug */
XmProcessTraversal(w, XmTRAVERSE_CURRENT);
XmProcessTraversal(w, XmTRAVERSE_CURRENT);
}
void MakePosVisible (Widget w, int item)
{
int top, visible;
XtVaGetValues(w, XmNtopItemPosition, &top,
XmNvisibleItemCount, &visible, NULL);
if (item < top)
XmListSetPos(w, item);
else if (item >= top+visible)
XmListSetBottomPos(w, item);
}
/* Menus */
typedef struct _menu_item {
char *label;
WidgetClass *class;
char mnemonic;
char *accelerator;
char *accel_text;
void (*callback)();
XtPointer callback_data;
} MenuItem;
Widget BuildMenu(Widget parent, char *title, char mnemonic, MenuItem *items)
{
Widget Pulldown, cascade, widget;
int i;
XmString str;
Pulldown = XmCreatePulldownMenu(parent, "_pulldown", NULL, 0);
str = XmStringCreateSimple(title);
cascade = XtVaCreateManagedWidget(title,
xmCascadeButtonWidgetClass, parent,
XmNsubMenuId, Pulldown,
XmNlabelString, str,
XmNmnemonic, mnemonic, NULL);
XmStringFree(str);
for (i=0; items[i].label != NULL; i++) {
widget = XtVaCreateManagedWidget(items[i].label, *items[i].class, Pulldown, NULL);
if (items[i].mnemonic)
XtVaSetValues (widget, XmNmnemonic, items[i].mnemonic, NULL);
if (items[i].accelerator) {
str = XmStringCreateSimple (items[i].accel_text);
XtVaSetValues (widget,
XmNaccelerator, items[i].accelerator,
XmNacceleratorText, str, NULL);
XmStringFree (str);
}
if (items[i].callback)
XtAddCallback (widget, XmNactivateCallback, items[i].callback, items[i].callback_data);
}
return cascade;
}
/* Bed commands */
/* from a message of Burt Juda in the UFGATE echo */
void mksoftcr (char *text) {
int c1 = 0; /* counter since last CR */
int c2 = 0; /* counter since last SPACE */
unsigned char *t, *s;
for (t=text; *t; t++)
{
c1++;
c2++;
*t = Pc2Iso (*t);
if ((*t == '\n') || (*t == '\r'))
{
c1 = 0;/* reset counters */
c2 = 0;
continue;
}
else
{
if ((*t == ' ') || (*t == '\t'))
{
s = t;
c2 = 0;
continue;
}
else
{
if (c1 > 78)
{
*s = '\n';
c1 = c2;
continue;
}
}
}
}
}
char *strip_re (char *l)
{
while (!strnicmp (l, "Re: ", 4))
l+=4;
return l;
}
void DisplayMsg(void)
{
char *buffer, *scan, *endkludge, *msgid, str[100];
FILE *msg;
int forw_repl, back_repl, c;
if (curr_msg==-1) {
/* clear all fields */
sprintf (str, "Area %s [0/0]", areas[curr_area].area_name);
XtVaSetValues (AreaWidget, Str (XmNlabelString, str), NULL);
XtVaSetValues (FromWidget, Str (XmNlabelString, ""), NULL);
XtVaSetValues (ToWidget, Str (XmNlabelString, ""), NULL);
XtVaSetValues (DateWidget, Str (XmNlabelString, ""), NULL);
XtVaSetValues (SubjWidget, Str (XmNlabelString, ""), NULL);
XmTextSetString (TextWidget, "");
msgid=NULL; replyid[0]=0;
return;
/* should shadow Reply/ReplyNetmail/Change/Delete/Save */
}
/* if netmail, set recv flag */
if ((curr_area==0) && (!(RECEIVED & headers[curr_msg].flags)) && (!stricmp (headers[curr_msg].to, sysop))) {
headers[curr_msg].flags |= RECEIVED;
sprintf (str, "%s.HDR", areas[curr_area].area_file);
msg=fopen (str, "r+");
fseek (msg, curr_msg*sizeof (struct Hdr), SEEK_SET);
fwrite (&headers[curr_msg], sizeof (struct Hdr), 1, msg);
fclose (msg);
}
buffer=XtMalloc(headers[curr_msg].size+1);
fseek (texts, headers[curr_msg].Mstart, SEEK_SET);
fread (buffer, 1, headers[curr_msg].size+1, texts);
buffer[headers[curr_msg].size]=0;
msgid=NULL; replyid[0]=0;
endkludge=buffer;
while (*endkludge=='\01') {
if (!strncmp(endkludge, "\01MSGID:", 7))
msgid=endkludge+7;
endkludge=strchr(endkludge, '\n')+1;
}
if (msgid) {
*strchr(msgid, '\n')=0;
strncpy (replyid, msgid, 24);
}
if (curr_area != 0) {
scan=strstr (endkludge, "\n * Origin:");
if (scan) {
scan=strchr (scan, '(');
echopoint=0;
sscanf (scan, "(%d:%d/%d.%d", &echozone, &echonet, &echonode, &echopoint);
}
} else {
echozone =headers[curr_msg].Ozone;
echonet =headers[curr_msg].Onet;
echonode =headers[curr_msg].Onode;
echopoint=headers[curr_msg].Opoint;
}
mksoftcr (endkludge);
XmTextSetString (TextWidget, endkludge);
XtFree (buffer);
/* scan area for replies */
strcpy (str, strip_re(headers[curr_msg].topic));
c=curr_msg+1; forw_repl=0;
while ((c<num_msgs) &&
!((!(headers[c].flags & DELETED)) && !stricmp (str, strip_re(headers[c].topic))))
c++;
if (c<num_msgs)
forw_repl=1;
c=curr_msg-1; back_repl=0;
while ((c>0) &&
!((!(headers[c].flags & DELETED)) && !stricmp (str, strip_re(headers[c].topic))))
c--;
if (c>0)
back_repl=1;
sprintf (str, "Area %s [%d/%d] %s%s%s%s%s%s%s%s%s%s%s %s%s", areas[curr_area].area_name, curr_msg+1, num_msgs,
(headers[curr_msg].flags&PRIVATE) ? "Pvt ":"",
(headers[curr_msg].flags&CRASH) ? "Crash ":"",
(headers[curr_msg].flags&RECEIVED) ? "Recv ":"",
(headers[curr_msg].flags&SENT) ? "Sent ":"",
(headers[curr_msg].flags&FILEATCH) ? "W/File ":"",
(headers[curr_msg].flags&MSGLOCAL) ? "Local ":"",
(headers[curr_msg].flags&KILLSEND) ? "K/Sent ":"",
(headers[curr_msg].flags&MSGHOLD) ? "Hold ":"",
(headers[curr_msg].flags&DIRECT) ? "Direct ":"",
(headers[curr_msg].flags&NOKILL) ? "N/Kill ":"",
(headers[curr_msg].flags&DELETED) ? "Deleted ":"",
back_repl ? "<-":"", forw_repl ? (back_repl?">":"->"):"");
XtVaSetValues (AreaWidget, Str (XmNlabelString, str), NULL);
if (curr_area==0)
sprintf (str, "From: %s (%d:%d/%d.%d)", headers[curr_msg].from, headers[curr_msg].Ozone, headers[curr_msg].Onet, headers[curr_msg].Onode, headers[curr_msg].Opoint);
else sprintf (str, "From: %s", headers[curr_msg].from);
XtVaSetValues (FromWidget, Str (XmNlabelString, str), NULL);
if (curr_area==0)
sprintf (str, "To: %s (%d:%d/%d.%d)", headers[curr_msg].to, headers[curr_msg].Dzone, headers[curr_msg].Dnet, headers[curr_msg].Dnode, headers[curr_msg].Dpoint);
else sprintf (str, "To: %s", headers[curr_msg].to);
XtVaSetValues (ToWidget, Str (XmNlabelString, str), NULL);
sprintf (str, "Date: %s", headers[curr_msg].time);
XtVaSetValues (DateWidget, Str (XmNlabelString, str), NULL);
sprintf (str, "Subj: %s", headers[curr_msg].topic);
XtVaSetValues (SubjWidget, Str (XmNlabelString, str), NULL);
}
void NextMessage(void)
{
curr_msg++;
if (curr_msg>num_msgs-1)
curr_msg=num_msgs-1;
if (curr_msg != -1) {
while ((headers[curr_msg].flags & DELETED) && (curr_msg<num_msgs-1))
curr_msg++;
if (headers[curr_msg].flags & DELETED)
while ((headers[curr_msg].flags & DELETED) && (curr_msg>0))
curr_msg--;
}
DisplayMsg();
}
void PreviousMessage(void)
{
curr_msg--;
if (curr_msg<0)
curr_msg=0;
if (num_msgs==0) {
curr_msg=-1;
return;
}
while ((headers[curr_msg].flags & DELETED) && (curr_msg>0))
curr_msg--;
if (headers[curr_msg].flags & DELETED)
while ((headers[curr_msg].flags & DELETED) && (curr_msg<num_msgs-1))
curr_msg++;
DisplayMsg();
}
void NextSubjMessage(void)
{
char sujet[100];
int c;
strcpy (sujet, strip_re(headers[curr_msg].topic));
c=curr_msg+1;
while ((c<num_msgs) &&
!((!(headers[c].flags & DELETED)) && !stricmp (sujet, strip_re(headers[c].topic))))
c++;
if (c<num_msgs)
curr_msg=c;
DisplayMsg();
}
void PreviousSubjMessage(void)
{
char sujet[100];
int c;
strcpy (sujet, strip_re(headers[curr_msg].topic));
c=curr_msg-1;
while ((c>0) &&
!((!(headers[c].flags & DELETED)) && !stricmp (sujet, strip_re(headers[c].topic))))
c--;
if (c>0)
curr_msg=c;
DisplayMsg();
}
void GotoMessageCB(Widget w, long data, XmSelectionBoxCallbackStruct *cbs)
{
int i;
char *value;
XmStringGetLtoR (cbs->value, XmSTRING_DEFAULT_CHARSET, &value);
i=atoi(value);
XtFree (value);
if ((i>0) && (i<=num_msgs))
curr_msg=i-1;
XtDestroyWidget (w);
DisplayMsg();
}
void GotoMessage(void)
{
Widget Popup;
XmString tmp;
Arg args[2];
tmp=XmStringCreateSimple ("Goto message number...");
XtSetArg (args[0], XmNselectionLabelString, tmp);
XtSetArg (args[1], XmNautoUnmanage, False);
Popup=XmCreatePromptDialog (RowCol, "GotoMessage", args, 2);
XmStringFree (tmp);
XtAddCallback (Popup, XmNokCallback, GotoMessageCB, NULL);
XtAddCallback (Popup, XmNcancelCallback, XtDestroyWidget, NULL);
XtUnmanageChild (XmSelectionBoxGetChild(Popup, XmDIALOG_HELP_BUTTON));
XtManageChild (Popup);
Focus (XmSelectionBoxGetChild(Popup, XmDIALOG_TEXT));
XtPopup (XtParent(Popup), XtGrabNone);
}
void OpenArea(int numero)
{
FILE *head;
char tmp[FILENAME_MAX];
if (curr_area!=-1)
areas[curr_area].lastread=curr_msg;
curr_area=numero;
sprintf (tmp, "%s.HDR", areas[numero].area_file);
head=fopen (tmp, "r");
if (head == NULL) {
num_msgs=0;
curr_msg=-1;
return;
}
fseek (head, 0, SEEK_END);
num_msgs=ftell (head) / sizeof (struct Hdr);
if (headers != NULL)
free (headers);
headers=malloc(ftell(head));
fseek (head, 0, SEEK_SET);
fread (headers, sizeof (struct Hdr), num_msgs, head);
fclose (head);
sprintf (tmp, "%s.MSG", areas[numero].area_file);
if (texts!=NULL)
fclose (texts);
texts=fopen (tmp, "r+");
curr_msg=areas[numero].lastread;
if (curr_msg>num_msgs-1)
curr_msg=num_msgs-1;
if (curr_msg != -1) {
while ((headers[curr_msg].flags & DELETED) && (curr_msg<num_msgs-1))
curr_msg++;
while ((headers[curr_msg].flags & DELETED) && (curr_msg>0))
curr_msg--;
}
DisplayMsg();
}
void NextArea (void)
{
int i=curr_area+1;
if (i >= num_areas)
i=0;
OpenArea (i);
}
void ChangeAreaCB (Widget w, long data, XmSelectionBoxCallbackStruct *cbs)
{
char *name;
int i, j;
XmStringGetLtoR (cbs->value, XmSTRING_DEFAULT_CHARSET, &name);
j=curr_area;
for (i=0; i<num_areas; i++)
if (!strcmp(name, areas[i].area_name)) {
j=i;
break;
}
XtFree (name);
XtDestroyWidget (w);
OpenArea(j);
}
void ChangeArea (void)
{
Widget Popup;
XmString *list;
char ligne[100];
int i;
list = (XmString *) XtMalloc(num_areas*sizeof(XmString));
for (i=0; i<num_areas; i++) {
strcpy (ligne, areas[i].area_name);
list[i]=XmStringCreateSimple (ligne);
}
Popup=XmCreateSelectionDialog (RowCol, "ChangeArea", NULL, 0);
XtVaSetValues (Popup, Str (XmNlistLabelString, "Select area..."),
XmNlistItems, list,
XmNlistItemCount, num_areas,
XmNmustMatch, True,
NULL);
XtVaSetValues (XmSelectionBoxGetChild(Popup, XmDIALOG_LIST), XmNvisibleItemCount, 12, NULL);
while (--i >= 0)
XmStringFree (list[i]);
XtFree (list);
XtAddCallback (Popup, XmNokCallback, ChangeAreaCB, NULL);
XtAddCallback (Popup, XmNcancelCallback, XtDestroyWidget, NULL);
XtUnmanageChild (XmSelectionBoxGetChild(Popup, XmDIALOG_HELP_BUTTON));
XtUnmanageChild (XmSelectionBoxGetChild(Popup, XmDIALOG_APPLY_BUTTON));
XtManageChild (Popup);
XtPopup (XtParent(Popup), XtGrabNone);
}
void ListMessageCB (Widget w, long data, XmSelectionBoxCallbackStruct *cbs)
{
int i;
char *value;
#if 0
problem with different fonts!!
XmStringContext context;
XmStringDirection direction;
XmStringCharSet charset;
Boolean separator;
i=XmStringInitContext (&context, cbs->value);
i=XmStringGetNextSegment (context, &value, &charset, &direction, &separator);
i=XmStringGetNextSegment (context, &value, &charset, &direction, &separator);
XmStringFreeContext (context);
#endif
XmStringGetLtoR (cbs->value, XmSTRING_DEFAULT_CHARSET, &value);
i=atoi(value+2);
XtFree (value);
if ((i>0) && (i<=num_msgs))
curr_msg=i-1;
XtDestroyWidget (w);
DisplayMsg();
}
void ListMessage (void)
{
Widget Popup;
XmString *list;
char ligne[100], sens;
int i, num; /* num=nombre de message dans la liste */
int curr_msg_list; /* index du message courant dans la liste */
list = malloc(num_msgs*sizeof(XmString));
num=0;
for (i=0; i<num_msgs; i++) {
if (i==curr_msg)
curr_msg_list=num;
if (!(headers[i].flags & DELETED)) {
sens=' ';
if (!stricmp (sysop, headers[i].from))
sens='<';
else if (!stricmp (sysop, headers[i].to))
sens='>';
if (i==curr_msg)
sens='=';
sprintf (ligne, "%c %3d %-20.20s %-20.20s %-40.40s", sens, i+1, headers[i].from, headers[i].to, headers[i].topic);
list[num++]=XmStringCreateSimple (ligne/*, i==curr_msg? "char2":"char1" problems with later recognition!!!*/);
}
}
Popup=XmCreateSelectionDialog (RowCol, "SelectMessage", NULL, 0);
XtVaSetValues (Popup, Str (XmNlistLabelString, "Select message..."),
XmNlistItems, list,
XmNlistItemCount, num,
XmNmustMatch, True,
NULL);
XtVaSetValues (XmSelectionBoxGetChild(Popup, XmDIALOG_LIST), XmNvisibleItemCount, 25, NULL);
while (--num >= 0)
XmStringFree (list[num]);
free (list);
XtAddCallback (Popup, XmNokCallback, ListMessageCB, NULL);
XtAddCallback (Popup, XmNcancelCallback, XtDestroyWidget, NULL);
XtUnmanageChild (XmSelectionBoxGetChild(Popup, XmDIALOG_HELP_BUTTON));
XtUnmanageChild (XmSelectionBoxGetChild(Popup, XmDIALOG_APPLY_BUTTON));
XtManageChild (Popup);
MakePosVisible (XmSelectionBoxGetChild(Popup, XmDIALOG_LIST), curr_msg_list+1);
XtPopup (XtParent(Popup), XtGrabNone);
}
int *setflags;
char topic_str[80], to_str[35];
Widget TopicWid, SendWid;
/* fermeture du dialogue principal -> mets le flag a un */
void EditCB (Widget w, int *done, XmSelectionBoxCallbackStruct *cbs)
{
char *value;
switch (cbs->reason) {
case XmCR_OK:
*done=1;
XmStringGetLtoR (cbs->value, XmSTRING_DEFAULT_CHARSET, &value);
strcpy (to_str, value);
XtFree (value);
break;
case XmCR_CANCEL:
*done=0;
break;
}
}
/* fermeture du selecteur de fichier pour With File */
void WFileCancelCB (Widget w, int *done, XmFileSelectionBoxCallbackStruct *cbs)
{
XtDestroyWidget (w);
*done=0;
}
void WFileCB (Widget w, int *done, XmFileSelectionBoxCallbackStruct *cbs)
{
char *value;
XmStringGetLtoR (cbs->value, XmSTRING_DEFAULT_CHARSET, &value);
strcpy (topic_str, value);
XtFree (value);
XmTextFieldSetString (TopicWid, topic_str);
XtDestroyWidget (w);
*done=1;
}
/* selection de With File -> affiche un selecteur de fichier */
int WFileSelect (void)
{
Widget FileSB;
Arg args[2];
int done;
XtSetArg (args[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
FileSB=XmCreateFileSelectionDialog (RowCol, "WFileSB", args, 1);
XtAddCallback (FileSB, XmNcancelCallback, WFileCancelCB, &done);
XtAddCallback (FileSB, XmNokCallback, WFileCB, &done);
XtManageChild (FileSB);
XtSetSensitive (XmFileSelectionBoxGetChild (FileSB, XmDIALOG_HELP_BUTTON), False);
XtPopup (XtParent(FileSB), XtGrabNone);
/* attente */
done=-1;
while (done==-1) {
XtAppProcessEvent (App, XtIMAll);
XSync (XtDisplay (SendWid), 0);
}
return done;
}
Widget Toggle;
/* changement d'etat d'un bouton */
void ToggleCB (Widget w, int mask, XmToggleButtonCallbackStruct *cbs)
{
if (cbs->set)
*setflags |= mask;
else
*setflags &= ~mask;
}
/* creation des boutons */
void Buttons (char *nom, int mask)
{
Widget w;
w=XtVaCreateManagedWidget (nom, xmToggleButtonGadgetClass, Toggle, NULL);
if (*setflags & mask)
XmToggleButtonSetState (w, True, False);
XtAddCallback (w, XmNvalueChangedCallback, ToggleCB, mask);
}
int EditHeader (int netmail, char **to, char **topic, int *dzone, int *dnet, int *dnode, int *dpoint, int *flags)
{
Widget w;
XmString tmp;
Arg args[4];
int done;
char *node, *ptr;
tmp=XmStringCreateSimple ("Send message to");
XtSetArg (args[0], XmNselectionLabelString, tmp);
XtSetArg (args[1], XmNautoUnmanage, False);
XtSetArg (args[2], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
SendWid=XmCreatePromptDialog (RowCol, "SendMessage", args, 3);
XmStringFree (tmp);
/* creation widget flags */
setflags=flags;
strcpy (topic_str, *topic);
strcpy (to_str, *to);
w=XtVaCreateManagedWidget ("Frame", xmFrameWidgetClass, SendWid, XmNshadowType, XmSHADOW_OUT, NULL);
w=XtVaCreateManagedWidget ("Frame1", xmRowColumnWidgetClass, w, NULL);
Toggle=XtVaCreateWidget ("Flags", xmRowColumnWidgetClass, w,
XmNpacking, XmPACK_COLUMN,
XmNorientation, XmVERTICAL,
XmNnumColumns, 7,
NULL);
if (netmail) {
Buttons ("Private", PRIVATE);
Buttons ("Crash", CRASH);
Buttons ("With File", FILEATCH);
Buttons ("Kill sent", KILLSEND);
Buttons ("Hold", MSGHOLD);
Buttons ("Direct", DIRECT);
Buttons ("CarbonCopy", CARBONCOPY);
if (*dzone+*dnet+*dnode+*dpoint != 0)
sprintf (to_str, "%s @ %d:%d/%d.%d", *to, *dzone, *dnet, *dnode, *dpoint);
}
/* creation widget topic */
w = XtVaCreateManagedWidget ("Frame2", xmRowColumnWidgetClass, w, XmNnumColumns, 2, NULL);
XtVaCreateManagedWidget ("Subject ", xmLabelGadgetClass, w, NULL);
TopicWid = XtVaCreateManagedWidget ("Topic", xmTextFieldWidgetClass, w, NULL);
XmTextFieldSetString(TopicWid, topic_str);
XtVaSetValues (SendWid, Str (XmNtextString, to_str), NULL);
XtAddCallback (SendWid, XmNokCallback, EditCB, &done);
XtAddCallback (SendWid, XmNcancelCallback, EditCB, &done);
XtUnmanageChild (XmSelectionBoxGetChild(SendWid, XmDIALOG_HELP_BUTTON));
XtManageChild (Toggle);
XtManageChild (SendWid);
Focus (XmSelectionBoxGetChild(SendWid, XmDIALOG_TEXT));
XtPopup (XtParent(SendWid), XtGrabNone);
done=-1;
while (done==-1) {
XtAppProcessEvent (App, XtIMAll);
XSync (XtDisplay (SendWid), 0);
}
if (done) {
/* get Topic */
if (FILEATCH & *setflags)
done=WFileSelect();
if (done) {
ptr=XmTextFieldGetString (TopicWid);
strcpy (topic_str, ptr);
XtFree (ptr);
*topic=topic_str;
*to=to_str;
if (netmail)
ParseAdr (to_str, dzone, dnet, dnode, dpoint);
}
}
XtUnmanageChild (SendWid);
XSync (XtDisplay(SendWid), 0);
XmUpdateDisplay (SendWid);
return done;
}
void WriteMsg (int numero, char *to, char *topic, int dzone, int dnet, int dnode, int dpoint, int flags)
{
FILE *msg;
char tmp[100];
struct Hdr head;
int len, i;
char c;
msg=fopen (temp1, "r");
if (msg==NULL)
return;
if (numero != curr_area) {
if (texts != NULL)
fclose (texts);
sprintf (tmp, "%s.MSG", areas[numero].area_file);
texts=fopen (tmp, "r+");
}
fseek (texts, 0, SEEK_END);
/* construction header */
head.Mstart=ftell (texts);
head.create=time(NULL);
head.up=head.parent=head.reads=head.cost=0;
head.flags=flags|MSGLOCAL;
head.Ozone=ourzone; head.Onet=ournet; head.Onode=ournode; head.Opoint=ourpoint;
head.Dzone=dzone; head.Dnet=dnet; head.Dnode=dnode; head.Dpoint=dpoint;
for (i=0; i<=7; i++) head.mailer[i]=0;
strncpy (head.from, sysop, 36); head.from[35]=0;
strncpy (head.to, to, 36); head.to[35]=0;
strncpy (head.topic, topic, 72); head.topic[71]=0;
strftime(head.time,20,"%d %b %y %H:%M:%S",localtime(&head.create));
len=0;
/* pid */
sprintf (tmp, "\01PID: Bed %s\n", BedVersion);
fputs (tmp, texts); len += strlen(tmp);
/* msgid */
if(ourpoint==0)
sprintf(tmp,"\01MSGID: %d:%d/%d %8.8lx\n", ourzone, ournet, ournode, head.create);
else
sprintf(tmp,"\01MSGID: %d:%d/%d.%d %8.8lx\n", ourzone, ournet, ournode, ourpoint, head.create);
fputs (tmp, texts); len += strlen(tmp);
/* reply */
if(replyid[0]) {
sprintf(tmp, "\01REPLY:%s\n", replyid);
fputs (tmp, texts); len += strlen(tmp);
}
/* texte */
while (!feof(msg)) {
c=getc(msg);
if (c==EOF) break;
putc (c, texts);
len++;
}
fclose (msg);
/* ecriture header */
head.size= (ushort) len;
sprintf (tmp, "%s.HDR", areas[numero].area_file);
msg=fopen (tmp, "a");
fwrite (&head, sizeof (struct Hdr), 1, msg);
fclose (msg);
if (numero != curr_area) {
fclose (texts);
sprintf (tmp, "%s.MSG", areas[curr_area].area_file);
texts=fopen (tmp, "r+");
}
}
char carbon_file[80];
void CarbonCB (Widget w, int *done, XmFileSelectionBoxCallbackStruct *cbs)
{
char *value;
XmStringGetLtoR (cbs->value, XmSTRING_DEFAULT_CHARSET, &value);
strcpy (carbon_file, value);
XtFree (value);
XtDestroyWidget (w);
*done=1;
}
void PostMsg (int numero, char *to, char *topic, int dzone, int dnet, int dnode, int dpoint, int flags)
{
FILE *msg;
FILE *carbon, *copy;
char ligne[100], carb_to[36], c;
int carb_zone, carb_net, carb_node, carb_point;
Arg args[2];
Widget FileSB;
int done;
/* edit from/to etc */
if (!EditHeader (!numero, &to, &topic, &dzone, &dnet, &dnode, &dpoint, &flags))
return;
/* starts text editor */
sprintf (ligne, "%s %s", edit_cmd, temp1);
system (ligne);
msg=fopen (temp1, "r");
if (msg==NULL)
return;
fclose (msg);
if (CARBONCOPY & flags) {
flags &= ~CARBONCOPY;
/* ask for filename */
XtSetArg (args[0], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
FileSB=XmCreateFileSelectionDialog (RowCol, "CarbonSB", args, 1);
XtAddCallback (FileSB, XmNcancelCallback, WFileCancelCB, &done);
XtAddCallback (FileSB, XmNokCallback, CarbonCB, &done);
XtManageChild (FileSB);
XtSetSensitive (XmFileSelectionBoxGetChild (FileSB, XmDIALOG_HELP_BUTTON), False);
XtPopup (XtParent(FileSB), XtGrabNone);
/* attente */
done=-1;
while (done==-1) {
XtAppProcessEvent (App, XtIMAll);
XSync (XtDisplay (SendWid), 0);
}
if (!done)
exit;
carbon = fopen (carbon_file, "r");
if (carbon==NULL)
exit;
copy = fopen (temp2, "w");
msg=fopen(temp1, "r");
while (!feof(msg)) {
c=getc(msg);
if (c==EOF) break;
putc (c, copy);
}
/* add CC information */
fprintf (copy, "\nOriginal to: %s (%d:%d/%d.%d)\n", to, dzone, dnet, dnode, dpoint);
while (!feof(carbon)) {
if (fgets (ligne, 100, carbon)) {
ParseAdr (ligne, &carb_zone, &carb_net, &carb_node, &carb_point);
strcpy (carb_to, ligne);
fprintf (copy, "CC: %s (%d:%d/%d.%d)\n", carb_to, carb_zone, carb_net, carb_node, carb_point);
}
}
putc ('\n', copy);
fclose (msg);
fclose (copy);
rename (temp2, temp1);
WriteMsg (numero, to, topic, dzone, dnet, dnode, dpoint, flags);
rewind (carbon);
while (!feof(carbon)) {
if (fgets (ligne, 100, carbon)) {
ParseAdr (ligne, &carb_zone, &carb_net, &carb_node, &carb_point);
strcpy (carb_to, ligne);
WriteMsg (numero, carb_to, topic, carb_zone, carb_net, carb_node, carb_point, flags | KILLSEND);
}
}
fclose (carbon);
} else
WriteMsg (numero, to, topic, dzone, dnet, dnode, dpoint, flags);
if (numero==curr_area)
OpenArea (curr_area);
}
void Wakeup(void)
{
FILE *led;
char ledfile[80], *mailer;
int area;
if (curr_area!=-1)
areas[curr_area].lastread=curr_msg;
mailer=getenv("MAILER");
if (mailer) sprintf (ledfile, "%s/led.new", mailer); else strcpy (ledfile, "led.new");
led=fopen(ledfile, "w");
for (area=0; area<num_areas; area++)
fprintf (led, "%-16s %-4d %d\n", areas[area].area_name,
areas[area].lastread==-1? 0:areas[area].lastread, areas[area].flags);
fclose (led);
exit (0);
}
void quote(FILE *msg)
{
char *buffer, *scan, *c, sys2;
int c1 = 0; /* counter since last CR */
int c2 = 0; /* counter since last SPACE */
unsigned char *t, *s;
if (echopoint)
fprintf (msg, "In a message of <%s>, %s (%d:%d/%d.%d) writes :\n\n", headers[curr_msg].time, headers[curr_msg].from, echozone, echonet, echonode, echopoint);
else fprintf (msg, "In a message of <%s>, %s (%d:%d/%d) writes :\n\n", headers[curr_msg].time, headers[curr_msg].from, echozone, echonet, echonode);
buffer=XtMalloc(headers[curr_msg].size+1);
fseek (texts, headers[curr_msg].Mstart, SEEK_SET);
fread (buffer, 1, headers[curr_msg].size+1, texts);
buffer[headers[curr_msg].size]=0;
/* mksoftcr */
for (t=buffer; *t; t++)
{
c1++;
c2++;
*t = Pc2Iso (*t);
if ((*t == '\n') || (*t == '\r'))
{
*t = '\n';
c1 = 0;/* reset counters */
c2 = 0;
continue;
}
else
{
if ((*t == ' ') || (*t == '\t'))
{
s = t;
c2 = 0;
continue;
}
else
{
if (c1 > 78-7)
{
*s = '\n';
c1 = c2;
continue;
}
}
}
}
c=strchr (headers[curr_msg].from, ' ');
sys2=' ';
if (c!=NULL)
sys2=*(c+1);
scan = buffer;
do {
c=strchr (scan, '\n');
if (c==NULL)
break;
if (scan[0]!='\01') {
*c=0;
if ((strlen(scan)>=1) && (scan[1]=='>'))
fprintf (msg, " %c%c>%s\n", headers[curr_msg].from[0], sys2, scan+1);
else if ((strlen(scan)>=5) && (scan[3]=='>'))
fprintf (msg, " %c%c>>%s\n", scan[1], scan[2], scan+5);
else fprintf (msg, " %c%c> %s\n", headers[curr_msg].from[0], sys2, scan);
}
scan=c+1;
} while (1);
XtFree (buffer);
}
void ReplyNetmail(void)
{
FILE *msg;
char topic[100];
if ((curr_area==0) || (curr_msg==-1))
return;
msg=fopen(temp1, "w");
fprintf (msg, "In area %s\n", areas[curr_area].area_name);
quote (msg);
fclose (msg);
if (strnicmp (headers[curr_msg].topic, "Re: ", 4))
sprintf (topic, "Re: %s", headers[curr_msg].topic);
else strcpy (topic, headers[curr_msg].topic);
PostMsg (0, headers[curr_msg].from, topic, echozone, echonet, echonode, echopoint, PRIVATE);
}
void Reply(void)
{
FILE *msg;
char topic[100];
if (curr_msg==-1)
return;
msg=fopen(temp1, "w");
quote (msg);
fclose (msg);
if (strnicmp (headers[curr_msg].topic, "Re: ", 4))
sprintf (topic, "Re: %s", headers[curr_msg].topic);
else strcpy (topic, headers[curr_msg].topic);
if (curr_area==0) PostMsg (curr_area, headers[curr_msg].from, topic, headers[curr_msg].Ozone, headers[curr_msg].Onet, headers[curr_msg].Onode, headers[curr_msg].Opoint, PRIVATE);
else PostMsg (curr_area, headers[curr_msg].from, topic, echozone, echonet, echonode, echopoint, 0);
}
void SaveMessageCB (Widget w, long data, XmFileSelectionBoxCallbackStruct *cbs)
{
char *buffer, *name;
FILE *fichier;
XmStringGetLtoR (cbs->value, XmSTRING_DEFAULT_CHARSET, &name);
fichier = fopen (name, "a");
/* header */
fprintf (fichier, "Area %s [%d/%d]\n", areas[curr_area].area_name, curr_msg+1, num_msgs);
if (curr_area==0) {
fprintf (fichier, "From: %s (%d:%d/%d.%d)\n", headers[curr_msg].from, headers[curr_msg].Ozone, headers[curr_msg].Onet, headers[curr_msg].Onode, headers[curr_msg].Opoint);
fprintf (fichier, "To: %s (%d:%d/%d.%d)\n", headers[curr_msg].to, headers[curr_msg].Dzone, headers[curr_msg].Dnet, headers[curr_msg].Dnode, headers[curr_msg].Dpoint);
} else {
fprintf (fichier, "From: %s\n", headers[curr_msg].from);
fprintf (fichier, "To: %s\n", headers[curr_msg].to);
}
fprintf (fichier, "Date: %s\n", headers[curr_msg].time);
fprintf (fichier, "Subj: %s\n", headers[curr_msg].topic);
fputs ("------\n\n", fichier);
/* texte */
buffer = XmTextGetString (TextWidget);
fwrite (buffer, 1, strlen(buffer), fichier);
XtFree (buffer);
XtFree (name);
fclose (fichier);
XtDestroyWidget (w);
}
void SaveMessage (void)
{
Widget Popup;
if (curr_msg==-1)
return;
Popup=XmCreateFileSelectionDialog (RowCol, "FileSB", NULL, 0);
XtAddCallback (Popup, XmNcancelCallback, XtDestroyWidget, NULL);
XtAddCallback (Popup, XmNokCallback, SaveMessageCB, NULL);
XtManageChild (Popup);
XtSetSensitive (XmFileSelectionBoxGetChild (Popup, XmDIALOG_HELP_BUTTON), False);
XtPopup (XtParent(Popup), XtGrabNone);
}
void PrintMessage (void)
{
FILE *fichier;
char *buffer;
if (curr_msg==-1)
return;
fichier = popen ("lpr ", "w");
/* header */
fprintf (fichier, "Area %s [%d/%d]\n", areas[curr_area].area_name, curr_msg+1, num_msgs);
if (curr_area==0) {
fprintf (fichier, "From: %s (%d:%d/%d.%d)\n", headers[curr_msg].from, headers[curr_msg].Ozone, headers[curr_msg].Onet, headers[curr_msg].Onode, headers[curr_msg].Opoint);
fprintf (fichier, "To: %s (%d:%d/%d.%d)\n", headers[curr_msg].to, headers[curr_msg].Dzone, headers[curr_msg].Dnet, headers[curr_msg].Dnode, headers[curr_msg].Dpoint);
} else {
fprintf (fichier, "From: %s\n", headers[curr_msg].from);
fprintf (fichier, "To: %s\n", headers[curr_msg].to);
}
fprintf (fichier, "Date: %s\n", headers[curr_msg].time);
fprintf (fichier, "Subj: %s\n", headers[curr_msg].topic);
fputs ("------\n\n", fichier);
/* texte */
buffer = XmTextGetString (TextWidget);
fwrite (buffer, 1, strlen(buffer), fichier);
XtFree (buffer);
pclose (fichier);
}
char *name;
Widget NumToWidget;
void SaveSeveralMessageCB2 (Widget w, long data, XmSelectionBoxCallbackStruct *cbs)
{
char *buffer, *endkludge, *value, *t;
FILE *fichier;
int from, to, i;
XmStringGetLtoR (cbs->value, XmSTRING_DEFAULT_CHARSET, &value);
to=atoi(value)-1;
XtFree (value);
value=XmTextFieldGetString (NumToWidget);
from=atoi(value)-1;
XtFree (value);
XtDestroyWidget (w);
if (to<from)
return;
fichier = fopen (name, "a");
XtFree (name);
for (i=from; i<=to; i++)
if ((i>=0) && (i<=num_msgs) && !(DELETED & headers[i].flags)) {
/* header */
fprintf (fichier, "Area %s [%d/%d]\n", areas[curr_area].area_name, i+1, num_msgs);
if (curr_area==0) {
fprintf (fichier, "From: %s (%d:%d/%d.%d)\n", headers[i].from, headers[i].Ozone, headers[i].Onet, headers[i].Onode, headers[i].Opoint);
fprintf (fichier, "To: %s (%d:%d/%d.%d)\n", headers[i].to, headers[i].Dzone, headers[i].Dnet, headers[i].Dnode, headers[i].Dpoint);
} else {
fprintf (fichier, "From: %s\n", headers[i].from);
fprintf (fichier, "To: %s\n", headers[i].to);
}
fprintf (fichier, "Date: %s\n", headers[i].time);
fprintf (fichier, "Subj: %s\n", headers[i].topic);
fputs ("------\n\n", fichier);
/* texte */
buffer=XtMalloc(headers[i].size+1);
fseek (texts, headers[i].Mstart, SEEK_SET);
fread (buffer, 1, headers[i].size+1, texts);
buffer[headers[i].size]=0;
/* zap les kludges du debut */
endkludge=buffer;
while (*endkludge=='\01')
endkludge=strchr(endkludge, '\n')+1;
/* zap les seen-by de la fin */
t=strstr (endkludge, "\01SEEN-BY");
if (t != NULL)
*t = 0;
/* zap les Via de la fin */
t=strstr (endkludge, "\01Via");
if (t != NULL)
*t = 0;
mksoftcr (endkludge);
fwrite (endkludge, 1, strlen(endkludge), fichier);
XtFree (buffer);
if (i!=to)
fprintf (fichier, "\n------------------------------------------------------------------------\n");
}
fclose (fichier);
}
void SaveSeveralMessageCB1 (Widget w, long data, XmFileSelectionBoxCallbackStruct *cbs)
{
Widget Popup;
XmString tmp;
Arg args[3];
XmStringGetLtoR (cbs->value, XmSTRING_DEFAULT_CHARSET, &name);
XtDestroyWidget (w);
tmp=XmStringCreateSimple (" to ");
XtSetArg (args[0], XmNselectionLabelString, tmp);
XtSetArg (args[1], XmNautoUnmanage, False);
XtSetArg (args[2], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
Popup=XmCreatePromptDialog (RowCol, "SelectMessages", args, 3);
XmStringFree (tmp);
w=XtVaCreateManagedWidget ("", xmRowColumnWidgetClass, Popup, NULL);
XtVaCreateManagedWidget ("Save message from ", xmLabelGadgetClass, w, NULL);
NumToWidget = XtVaCreateManagedWidget ("SaveTo", xmTextFieldWidgetClass, w, NULL);
XtAddCallback (Popup, XmNokCallback, SaveSeveralMessageCB2, NULL);
XtAddCallback (Popup, XmNcancelCallback, XtDestroyWidget, NULL);
XtUnmanageChild (XmSelectionBoxGetChild(Popup, XmDIALOG_HELP_BUTTON));
XtManageChild (Popup);
Focus (NumToWidget);
XtPopup (XtParent(Popup), XtGrabNone);
}
void SaveSeveralMessage (void)
{
Widget Popup;
if (curr_msg==-1)
return;
Popup=XmCreateFileSelectionDialog (RowCol, "Save messages", NULL, 0);
XtAddCallback (Popup, XmNcancelCallback, XtDestroyWidget, NULL);
XtAddCallback (Popup, XmNokCallback, SaveSeveralMessageCB1, NULL);
XtManageChild (Popup);
XtSetSensitive (XmFileSelectionBoxGetChild (Popup, XmDIALOG_HELP_BUTTON), False);
XtPopup (XtParent(Popup), XtGrabNone);
}
void EnterMessage (void)
{
unlink (temp1);
replyid[0]=0;
PostMsg (curr_area, !curr_area? "":"All", "", 0, 0, 0, 0, !curr_area? PRIVATE:0);
}
void DeleteMessage (void)
{
FILE *msg;
char tmp[FILENAME_MAX];
if (curr_msg==-1)
return;
headers[curr_msg].flags |= DELETED;
sprintf (tmp, "%s.HDR", areas[curr_area].area_file);
msg=fopen (tmp, "r+");
fseek (msg, curr_msg*sizeof (struct Hdr), SEEK_SET);
fwrite (&headers[curr_msg], sizeof (struct Hdr), 1, msg);
fclose (msg);
OpenArea (curr_area);
}
#define DeleteFlag 1
#define UndeleteFlag 0
void DeleteSeveralCB(Widget w, int flag, XmSelectionBoxCallbackStruct *cbs)
{
int i, from, to;
char *value;
FILE *msg;
char tmp[100];
XmStringGetLtoR (cbs->value, XmSTRING_DEFAULT_CHARSET, &value);
to=atoi(value)-1;
XtFree (value);
value=XmTextFieldGetString (NumToWidget);
from=atoi(value)-1;
XtFree (value);
if (to == -1)
to=from;
if (from < 0)
from=0;
if (to > num_msgs)
to=num_msgs;
if (to < from) {
XtDestroyWidget (w);
return;
}
sprintf (tmp, "%s.HDR", areas[curr_area].area_file);
msg=fopen (tmp, "r+");
for (i=from; i<=to; i++)
if (flag) headers[i].flags |= DELETED;
else headers[i].flags &= ~(DELETED+KILLSEND);
fseek (msg, from*sizeof (struct Hdr), SEEK_SET);
fwrite (&headers[from], sizeof (struct Hdr), to-from+1, msg);
fclose (msg);
XtDestroyWidget (w);
OpenArea (curr_area);
}
void DeleteSeveralMessage(Widget z, int flag)
{
Widget Popup, w;
XmString tmp;
Arg args[2];
if (curr_msg==-1)
return;
tmp=XmStringCreateSimple (" to ");
XtSetArg (args[0], XmNselectionLabelString, tmp);
XtSetArg (args[1], XmNautoUnmanage, False);
Popup=XmCreatePromptDialog (RowCol, "SelectMessages", args, 2);
XmStringFree (tmp);
w=XtVaCreateManagedWidget ("", xmRowColumnWidgetClass, Popup, NULL);
if (flag)
XtVaCreateManagedWidget ("Delete messages from ", xmLabelGadgetClass, w, NULL);
else
XtVaCreateManagedWidget ("Undelete messages from ", xmLabelGadgetClass, w, NULL);
NumToWidget = XtVaCreateManagedWidget ("DeleteTo", xmTextFieldWidgetClass, w, NULL);
XtAddCallback (Popup, XmNokCallback, DeleteSeveralCB, flag);
XtAddCallback (Popup, XmNcancelCallback, XtDestroyWidget, NULL);
XtUnmanageChild (XmSelectionBoxGetChild(Popup, XmDIALOG_HELP_BUTTON));
XtManageChild (Popup);
Focus (NumToWidget);
XtPopup (XtParent(Popup), XtGrabNone);
}
void ChangeMessage(void)
{
FILE *msg;
char tmp[100], *buffer;
struct Hdr head;
int len, i;
char c;
if (curr_msg==-1)
return;
/* ca supprime les kludges du message (ou ca les modifient) */
/* edition */
remove (temp1);
buffer = XmTextGetString (TextWidget);
msg=fopen (temp1, "w");
fwrite (buffer, 1, strlen(buffer), msg);
XtFree (buffer);
fclose (msg);
sprintf (tmp, "%s %s", edit_cmd, temp1);
system (tmp);
msg=fopen (temp1, "r");
fseek (texts, 0, SEEK_END);
/* construction header */
head=headers[curr_msg];
head.Mstart=ftell (texts);
head.create=time(NULL);
head.flags=(head.flags|MSGLOCAL) & (~SENT);
head.mailer[7]=0;
head.Ozone=ourzone; head.Onet=ournet; head.Onode=ournode; head.Opoint=ourpoint;
strncpy (head.from, sysop, 36); head.from[35]=0;
strftime(head.time,20,"%d %b %y %H:%M:%S",localtime(&head.create));
len=0;
/* pid */
sprintf (tmp, "\01PID: Bed %s\n", BedVersion);
fputs (tmp, texts); len += strlen(tmp);
/* msgid */
if(ourpoint==0)
sprintf(tmp,"\01MSGID: %d:%d/%d %8.8lx\n", ourzone, ournet, ournode, head.create);
else
sprintf(tmp,"\01MSGID: %d:%d/%d.%d %8.8lx\n", ourzone, ournet, ournode, ourpoint, head.create);
fputs (tmp, texts); len += strlen(tmp);
/* texte */
while (!feof(msg)) {
c=getc(msg);
if (c==EOF) break;
putc (c, texts);
len++;
}
fclose (msg);
/* ecriture header */
head.size= (ushort) len;
sprintf (tmp, "%s.HDR", areas[curr_area].area_file);
msg=fopen (tmp, "a");
fwrite (&head, sizeof (struct Hdr), 1, msg);
/* effacement de l'ancien message */
headers[curr_msg].flags |= DELETED;
fseek (msg, curr_msg*sizeof (struct Hdr), SEEK_SET);
fwrite (&headers[curr_msg], sizeof (struct Hdr), 1, msg);
fclose (msg);
OpenArea (curr_area);
}
void ForwardCB(Widget w, long data, XmSelectionBoxCallbackStruct *cbs)
{
char *value, *node, *buffer, to_str[35];
int dzone, dnet, dnode, dpoint;
FILE *msg, *orig;
XmStringGetLtoR (cbs->value, XmSTRING_DEFAULT_CHARSET, &value);
strcpy (to_str, value);
XtFree (value);
ParseAdr (to_str, &dzone, &dnet, &dnode, &dpoint);
msg=fopen(temp1, "w");
if (curr_area==0) {
fprintf (msg, "* Originally from: %s (%d:%d/%d.%d)\n", headers[curr_msg].from, headers[curr_msg].Ozone, headers[curr_msg].Onet, headers[curr_msg].Onode, headers[curr_msg].Opoint);
fprintf (msg, "* Originally to: %s (%d:%d/%d.%d)\n\n", headers[curr_msg].to, headers[curr_msg].Dzone, headers[curr_msg].Dnet, headers[curr_msg].Dnode, headers[curr_msg].Dpoint);
} else {
fprintf (msg, "* Originally in area %s\n", areas[curr_area].area_name);
fprintf (msg, "* Originally from: %s\n", headers[curr_msg].from);
fprintf (msg, "* Originally to: %s\n\n", headers[curr_msg].to);
}
buffer = XmTextGetString (TextWidget);
fwrite (buffer, 1, strlen(buffer), msg);
XtFree (buffer);
fclose (msg);
WriteMsg (0, to_str, headers[curr_msg].topic, dzone, dnet, dnode, dpoint, PRIVATE+KILLSEND);
XtDestroyWidget (w);
OpenArea(curr_area);
}
void Forward(void)
{
Widget Popup;
XmString tmp;
Arg args[3];
tmp=XmStringCreateSimple ("Forward message to...");
XtSetArg (args[0], XmNselectionLabelString, tmp);
XtSetArg (args[1], XmNautoUnmanage, False);
XtSetArg (args[2], XmNtextColumns, 35);
Popup=XmCreatePromptDialog (RowCol, "ForwardMessage", args, 3);
XmStringFree (tmp);
XtAddCallback (Popup, XmNokCallback, ForwardCB, NULL);
XtAddCallback (Popup, XmNcancelCallback, XtDestroyWidget, NULL);
XtUnmanageChild (XmSelectionBoxGetChild(Popup, XmDIALOG_HELP_BUTTON));
XtManageChild (Popup);
Focus (XmSelectionBoxGetChild(Popup, XmDIALOG_TEXT));
XtPopup (XtParent(Popup), XtGrabNone);
}
void insensitive (char *a, char *b)
{
while (*a) {
if ((*b == '[') || (*b == ']') || (*b == '*') || (*b == '.') || (*b == '\\')) {
*b++ = '\\';
*b++ = *a;
} else {
*b++ = '[';
*b++ = tolower (*a);
*b++ = toupper (*a);
*b++ = ']';
}
a++;
}
*b=0;
}
void SearchSame(Widget w, Widget data)
{
int num;
char *buffer;
num=curr_msg+1;
while (num<num_msgs) {
if (!(headers[num].flags & DELETED)) {
buffer=XtMalloc(headers[num].size+1);
fseek (texts, headers[num].Mstart, SEEK_SET);
fread (buffer, 1, headers[num].size+1, texts);
buffer[headers[num].size]=0;
if (re_exec(headers[num].topic) || re_exec(headers[num].to) ||
re_exec(headers[num].from) || re_exec(buffer)) {
XtFree (buffer);
curr_msg=num;
num=0; /* use as a found flag */
break;
}
XtFree (buffer);
}
num++;
}
DisplayMsg();
/* destroy "Search" box if exist and last string not found */
if (data && num)
XtDestroyWidget (data);
}
void SearchCB(Widget w, long data, XmSelectionBoxCallbackStruct *cbs)
{
char *value;
XmStringGetLtoR (cbs->value, XmSTRING_DEFAULT_CHARSET, &value);
re_comp (value);
XtFree (value);
SearchSame (NULL, w);
}
void Search(void)
{
Widget Popup;
XmString tmp;
Arg args[3];
tmp=XmStringCreateSimple ("Search ...");
XtSetArg (args[0], XmNselectionLabelString, tmp);
XtSetArg (args[1], XmNautoUnmanage, False);
XtSetArg (args[2], XmNtextColumns, 35);
Popup=XmCreatePromptDialog (RowCol, "Search", args, 3);
XmStringFree (tmp);
XtAddCallback (Popup, XmNokCallback, SearchCB, NULL);
XtAddCallback (Popup, XmNcancelCallback, XtDestroyWidget, NULL);
XtUnmanageChild (XmSelectionBoxGetChild(Popup, XmDIALOG_HELP_BUTTON));
XtManageChild (Popup);
Focus (XmSelectionBoxGetChild(Popup, XmDIALOG_TEXT));
XtPopup (XtParent(Popup), XtGrabNone);
}
/* add the sender of the current message to the user's list */
/* does not check for duplicate entry ! */
void AddSender(void)
{
FILE *ulist;
char *p, ligne[50];
p=getenv ("MAILER");
if (p)
sprintf (ligne, "%s/ulist.txt", p);
else
strcpy (ligne, "ulist.txt");
ulist=fopen (ligne, "a");
if (curr_area==0)
fprintf (ulist, "%s\t%d:%d/%d.%d\n", headers[curr_msg].from, headers[curr_msg].Ozone, headers[curr_msg].Onet, headers[curr_msg].Onode, headers[curr_msg].Opoint);
else
fprintf (ulist, "%s\t%d:%d/%d.%d\n", headers[curr_msg].from, echozone, echonet, echonode, echopoint);
fclose (ulist);
}
void AboutBed(void)
{
Widget Popup;
XmString tmp;
Arg args[3];
char str[200];
sprintf (str, " Bed v%s - Bermuda EDitor \n\n (c) Vincent Pomey 1993\n", BedVersion);
tmp=XmStringCreateLtoR (str, XmSTRING_DEFAULT_CHARSET);
XtSetArg (args[0], XmNmessageString, tmp);
XtSetArg (args[1], XmNautoUnmanage, False);
Popup=XmCreateInformationDialog (RowCol, "About Bed", args, 2);
XmStringFree (tmp);
XtAddCallback (Popup, XmNokCallback, XtDestroyWidget, NULL);
XtUnmanageChild (XmMessageBoxGetChild(Popup, XmDIALOG_HELP_BUTTON));
XtUnmanageChild (XmMessageBoxGetChild(Popup, XmDIALOG_CANCEL_BUTTON));
XtManageChild (Popup);
XtPopup (XtParent(Popup), XtGrabNone);
}
MenuItem file_items[] = {
{ "Change Area...", &xmPushButtonGadgetClass, 'A', "Ctrl<Key>A", "^A", ChangeArea, NULL },
{ "Next Area", &xmPushButtonGadgetClass, 'W', "Ctrl<Key>W", "^W", NextArea, NULL },
{ "Save current...",&xmPushButtonGadgetClass, 'S', "Ctrl<Key>S", "^S", SaveMessage, NULL },
{ "Save several...",&xmPushButtonGadgetClass,NULL, NULL, NULL, SaveSeveralMessage, NULL },
{ "Print current...",&xmPushButtonGadgetClass, 'P', "Ctrl<Key>P", "^P", PrintMessage, NULL },
{ "", &xmSeparatorGadgetClass, NULL, NULL, NULL, NULL, NULL },
{ "Quit", &xmPushButtonGadgetClass, 'Q', "Ctrl<Key>Q", "^Q", Wakeup, NULL },
NULL},
message_items[] = {
{ "Next", &xmPushButtonGadgetClass, NULL, "<Key>End", "->", NextMessage, NULL },
{ "Previous", &xmPushButtonGadgetClass, NULL, "<Key>Begin", "<-", PreviousMessage, NULL },
{ "Goto...", &xmPushButtonGadgetClass, 'G', "Ctrl<Key>G", "^G", GotoMessage, NULL },
{ "List...", &xmPushButtonGadgetClass, 'L', "Ctrl<Key>L", "^L", ListMessage, NULL },
{ "Next Subj", &xmPushButtonGadgetClass, NULL, "Ctrl<Key>I", "^I", NextSubjMessage, NULL },
{ "Previous Subj", &xmPushButtonGadgetClass, NULL, "Ctrl<Key>U", "^U", PreviousSubjMessage, NULL },
{ "", &xmSeparatorGadgetClass, NULL, NULL, NULL, NULL, NULL },
{ "Delete current", &xmPushButtonGadgetClass, 'D', "Ctrl<Key>D", "^D", DeleteMessage, NULL },
{ "Delete several", &xmPushButtonGadgetClass, NULL, "Ctrl<Key>K", "^K", DeleteSeveralMessage, (XtPointer) DeleteFlag },
{ "Undelete", &xmPushButtonGadgetClass, NULL, NULL, NULL, DeleteSeveralMessage, (XtPointer) UndeleteFlag },
{ "Change", &xmPushButtonGadgetClass, 'C', "Ctrl<Key>C", "^C", ChangeMessage, NULL },
NULL},
edit_items[] = {
{ "Enter...", &xmPushButtonGadgetClass, 'E', "Ctrl<Key>E", "^E", EnterMessage, NULL },
{ "Reply", &xmPushButtonGadgetClass, 'R', "Ctrl<Key>R", "^R", Reply, NULL },
{ "Reply in Netmail", &xmPushButtonGadgetClass,'N', "Ctrl<Key>N", "^N", ReplyNetmail, NULL },
{ "Forward...", &xmPushButtonGadgetClass, 'F', "Ctrl<Key>F", "^F", Forward, NULL },
NULL},
misc_items[] = {
{ "Search...", &xmPushButtonGadgetClass, NULL, NULL, NULL, Search, NULL },
{ "Search same", &xmPushButtonGadgetClass, NULL, NULL, NULL, SearchSame, NULL },
{ "Add sender in ulist", &xmPushButtonGadgetClass, NULL, NULL, NULL, AddSender, NULL },
NULL},
help_items[] = {
{ "About Bed", &xmPushButtonGadgetClass, NULL, NULL, NULL, AboutBed, NULL },
NULL};
main(argc, argv)
int argc;
char *argv[];
{
Widget TopLevel, MainWindow, MenuBar, FilePullDown, MessagePullDown;
Arg args[5];
Pixmap pixmap;
Screen *screen;
/* lecture fichiers de config */
readconfig();
readareas();
strcpy (temp1, "/tmp/bedXXXXXX"); mktemp (temp1); fclose (fopen (temp1, "w"));
strcpy (temp2, "/tmp/bedXXXXXX"); mktemp (temp2); fclose (fopen (temp1, "w"));
/* initialisation Motif */
TopLevel = XtVaAppInitialize(&App, "Bed", NULL, 0, &argc, argv, NULL, NULL);
XtGetApplicationResources (TopLevel, &edit_cmd, ressources, XtNumber(ressources), NULL, 0);
MainWindow = XtVaCreateManagedWidget("mainwin", xmMainWindowWidgetClass, TopLevel, NULL);
pixmap = XCreateBitmapFromData (XtDisplay(TopLevel), XtScreen(TopLevel)->root, bed_bits, bed_width, bed_height);
XtVaSetValues (TopLevel, XmNiconPixmap, pixmap, NULL);
/* barre de menu */
MenuBar = XmCreateMenuBar(MainWindow,"menubar", NULL, 0);
BuildMenu (MenuBar, "File", 'F', file_items);
BuildMenu (MenuBar, "Edit", 'E', edit_items);
BuildMenu (MenuBar, "Message", 'M', message_items);
BuildMenu (MenuBar, "Others", 'O', misc_items);
XtVaSetValues (MenuBar, XmNmenuHelpWidget, BuildMenu (MenuBar, "Help", 'H', help_items), NULL);
XtManageChild(MenuBar);
/* text area */
RowCol = XtVaCreateWidget ("WorkArea", xmRowColumnWidgetClass, MainWindow, XmNpacking, XmPACK_TIGHT, NULL);
AreaWidget = XtVaCreateManagedWidget ("Area", xmLabelGadgetClass, RowCol, NULL);
FromWidget = XtVaCreateManagedWidget ("From", xmLabelGadgetClass, RowCol, NULL);
ToWidget = XtVaCreateManagedWidget ("To", xmLabelGadgetClass, RowCol, NULL);
DateWidget = XtVaCreateManagedWidget ("Date", xmLabelGadgetClass, RowCol, NULL);
SubjWidget = XtVaCreateManagedWidget ("Subj", xmLabelGadgetClass, RowCol, NULL);
XtSetArg (args[0], XmNeditable, False);
XtSetArg (args[1], XmNeditMode, XmMULTI_LINE_EDIT);
XtSetArg (args[2], XmNcursorPositionVisible, False);
TextWidget = XmCreateScrolledText (RowCol, "message", args, 3);
XtManageChild (TextWidget);
XtManageChild (RowCol);
XmMainWindowSetAreas (MainWindow, MenuBar, NULL, NULL, NULL, RowCol);
OpenArea (0);
XtRealizeWidget(TopLevel);
XtAppMainLoop(App);
unlink (temp1);
unlink (temp2);
}